home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
edit
/
xvisrc.zip
/
UNIX.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-07-28
|
21KB
|
982 lines
/* Copyright (c) 1990,1991,1992 Chris and John Downey */
#ifndef lint
static char *sccsid = "@(#)unix.c 2.1 (Chris & John Downey) 7/29/92";
#endif
/***
* program name:
xvi
* function:
PD version of UNIX "vi" editor, with extensions.
* module name:
unix.c
* module function:
System interface routines for all versions of UNIX.
* history:
STEVIE - ST Editor for VI Enthusiasts, Version 3.10
Originally by Tim Thompson (twitch!tjt)
Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
Heavily modified by Chris & John Downey
***/
#include "xvi.h"
#ifndef SIGINT
# include <signal.h> /* get signals for call_shell() */
#endif
#ifdef BSD
# include <sys/wait.h> /* get wait stuff for call_shell() */
typedef union wait Wait_t;
#else
typedef int Wait_t;
#endif
/*
* CTRL is defined by sgtty.h (or by a file it includes)
* so we undefine it here to avoid conflicts with the
* version defined in "xvi.h".
*/
#undef CTRL
#ifdef sun
# ifndef TERMIOS
# define TERMIOS
# endif
#endif
#ifdef TERMIOS
# ifndef TERMIO
# define TERMIO
# endif
#endif
#ifdef TERMIO
# ifdef TERMIOS
# include <termios.h>
typedef struct termios Termstate;
# define getstate(p) ((void) tcgetattr(0, (p)))
# define setstate(p) ((void) tcsetattr(0, TCSANOW, (p)))
# define w_setstate(p) ((void) tcsetattr(0, TCSADRAIN, (p)))
# else /* no TERMIOS */
# include <termio.h>
typedef struct termio Termstate;
# define getstate(p) ((void) ioctl(0,TCGETA,(char *)(p)))
# define setstate(p) ((void) ioctl(0,TCSETA,(char *)(p)))
# define w_setstate(p) ((void) ioctl(0,TCSETAW,(char *)(p)))
# endif /* no TERMIOS */
/*
* Table of line speeds ... exactly 16 long, and the CBAUD mask
* is 017 (i.e. 15) so we will never access outside the array.
*/
short speeds[] = {
/* B0 */ 0,
/* B50 */ 50,
/* B75 */ 75,
/* B110 */ 110,
/* B134 */ 134,
/* B150 */ 150,
/* B200 */ 200,
/* B300 */ 300,
/* B600 */ 600,
/* B1200 */ 1200,
/* B1800 */ 1800,
/* B2400 */ 2400,
/* B4800 */ 4800,
/* B9600 */ 9600,
/* EXTA */ 19200, /* not defined at V.2 */
/* EXTB */ 38400, /* not defined at V.2 */
};
#else /* not TERMIO */
# include <sgtty.h>
typedef struct sgttyb Termstate;
static struct tchars ckd_tchars, raw_tchars;
static struct ltchars ckd_ltchars, raw_ltchars;
# ifdef FD_SET
# define fd_set_type fd_set
# else /* FD_SET not defined */
/*
* BSD 4.2 doesn't have these macros.
*/
typedef int fd_set_type;
# define FD_ZERO(p) (*(p) = 0)
# define FD_SET(f,p) (*(p) |= (1 << (f)))
# endif /* FD_SET not defined */
#endif /* not TERMIO */
static Termstate cooked_state, raw_state;
#undef CTRL
#ifdef SETVBUF_AVAIL
/*
* Output buffer to save function calls.
*/
static char outbuffer[128];
#endif
#ifdef MEMTEST
# include <sys/resource.h>
#endif /* MEMTEST */
/*
* Expected for termcap's benefit.
*/
short ospeed; /* tty's baud rate */
/*
* We sometimes use a lot of system calls while trying to read from
* the keyboard; these are needed to make our automatic buffer
* preservation and input timeouts work properly. Nevertheless, it
* is possible that, with this much overhead, a reasonably fast typist
* could get ahead of us, so we do a small amount of input buffering
* to reduce the number of system calls.
*
* This variable gives the number of characters in the buffer.
*/
static int kb_nchars;
/*
* Get a single byte from the keyboard.
*
* If the keyboard input buffer is empty, & read() fails or times out,
* return EOF.
*/
static int
kbgetc()
{
static unsigned char kbuf[48];
static unsigned char *kbp;
if (kb_nchars <= 0) {
int nread;
if ((nread = read(0, (char *) kbuf, sizeof kbuf)) <= 0) {
return EOF;
} else {
kb_nchars = nread;
kbp = kbuf;
}
}
--kb_nchars;
return(*kbp++);
}
#ifdef TERMIO
/*
* Set a timeout on standard input. 0 means no timeout.
*
* This depends on raw_state having been properly initialized, which
* should have been done by sys_startv().
*/
static void
input_timeout(msec)
long msec;
{
int vtime;
static int lastvtime;
/*
* If the device state hasn't been changed since last time, we
* don't need to do anything.
*/
if ((vtime = (msec + 99) / 100) != lastvtime) {
lastvtime = vtime;
raw_state.c_cc[VMIN] = (vtime == 0 ? 1 : 0);
raw_state.c_cc[VTIME] = vtime;
setstate(&raw_state);
}
}
#endif /* TERMIO */
/*
* Get a character from the keyboard.
*
* Make sure screen is updated first.
*/
int
inch(timeout)
long timeout;
{
int c;
/*
* If we had characters left over from last time, return one.
*
* Note that if this happens, we don't call flush_output().
*/
if (kb_nchars > 0) {
return(kbgetc());
}
/*
* Need to get a character. First, flush output to the screen.
*/
flush_output();
#ifdef TERMIO
if (timeout != 0) {
input_timeout(timeout);
c = kbgetc();
input_timeout(0L);
return(c);
}
#else /* no TERMIO */
if (timeout != 0) {
struct timeval tv;
fd_set_type readfds;
tv.tv_sec = (long) (timeout / 1000);
tv.tv_usec = ((long) timeout * 1000) % (long) 1000000;
FD_ZERO(&readfds);
FD_SET(0, &readfds);
/*
* If select does not return 0, some input is available
* (ignoring the possibility of errors). Otherwise, we
* timed out, so return EOF.
*/
if (select(1, &readfds, (fd_set_type *) NULL,
(fd_set_type *) NULL, &tv) == 0) {
return(EOF);
}
}
#endif /* no TERMIO */
/*
* Keep trying until we get at least one character.
*/
while ((c = kbgetc()) == EOF)
;
return(c);
}
#if !(defined(__STDC__) || (defined(ultrix) && defined(mips)))
/*
* If we have ANSI C, we should have strerror() anyway. Also, Ultrix
* on DECStations provides it.
*/
const char *
strerror(err)
int err;
{
extern char *sys_errlist[];
extern int sys_nerr;
return(
err == 0 ?
"No error"
:
(err > 0 && err < sys_nerr) ?
sys_errlist[err]
:
"Unknown error"
);
}
#endif /* !(defined(__STDC__) || (defined(ultrix) && defined(mips))) */
static int
runvp(args)
char **args;
{
int pid;
Wait_t status;
pid = fork();
switch (pid) {
case -1: /* fork() failed */
return(-1);
case 0: /* this is the child */
(void) signal(SIGINT, SIG_DFL);
(void) signal(SIGQUIT, SIG_DFL);
(void) execvp(args[0], args);
/*
* Couldn't do it ... use standard output functions here
* because none of xvi's higher-level functions are usable
* from this module.
*/
(void) fputs("\007Can't execute ", stdout);
(void) fputs(args[0], stdout);
(void) fputs("\n(", stdout);
(void) fputs(strerror(errno), stdout);
(void) fputs(")\nHit return to continue", stdout);
(void) fflush(stdout);
(void) getc(stdin);
exit(1);
default: /* this is the parent */
while (wait(&status) != pid)
;
return(0);
}
}
int
call_shell(sh)
char *sh;
{
static char *args[] = { NULL, NULL };
args[0] = sh;
return(runvp(args));
}
int
call_system(command)
char *command;
{
static char *args[] = { NULL, "-c", NULL, NULL };
if (Ps(P_shell) == NULL) {
(void) puts("\007Can't execute command without SHELL parameter");
return(-1);
}
args[0] = Ps(P_shell);
args[2] = command;
return(runvp(args));
}
#ifdef ITIMER_REAL
static int
nothing()
{
return(0);
}
#endif
/*
* Delay for a short time - preferably less than 1 second.
* This is for use by showmatch, which wants to hold the
* cursor over the matching bracket for just long enough
* that it will be seen.
*/
void
delay()
{
#ifdef ITIMER_REAL
struct itimerval timer;
(void) signal(SIGALRM, nothing);
/*
* We want to pause for 200 msec (1/5th of a second) here,
* as this seems like a reasonable figure. Note that we can
* assume that the implementation will have defined tv_usec
* of a type large enough to hold up to 999999, since that's
* the largest number of microseconds we can possibly need.
*/
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
timer.it_value.tv_sec = 0;
timer.